package com.yulinlin.jdbc.mysql;

import com.yulinlin.core.lambda.LambdaPropertyFunction;
import com.yulinlin.core.wrapper.IParamsWrapper;
import com.yulinlin.jdbc.model.anno.JoinField;
import com.yulinlin.lang.util.LambdaUtils;
import com.yulinlin.lang.util.ReflectionUtil;
import com.yulinlin.lang.util.StringUtil;

import java.lang.reflect.Field;
import java.util.*;

/**
 *
 * 顺序无关
 */
public class MysqlParamsWrapper implements IParamsWrapper {

    private List<Object> list ;

    private int i = 0;

    private Map<String,Object> params;

    private Map<String,String> aliasMap;

    public MysqlParamsWrapper() {
        this.list = new ArrayList<>();
        this.params = new HashMap<>();
        this.aliasMap = new HashMap<>();
    }

    @Override
    public String push(Object val) {
        this.list.add(val);
        this.i++;
        String key =  "#{"+this.i+"}";
        this.params.put(key,val);
        return  key;
    }

    @Override
    public List<String> pushList(Collection<?> params) {
        List<String> list = new ArrayList<>();
        for (Object row : params){
            list.add(this.push(row));
        }
        return list;
    }

    @Override
    public Map<String, Object> getParams() {
        return this.params;
    }

    @Override
    public void put(String key, Object value) {
        params.put(key,value);
    }

    @Override
    public void putAll(Map<String, Object> map) {
        params.putAll(map);
    }

    @Override
    public String fieldToColumnName(Field f) {
        JoinField joinField =  f.getAnnotation(JoinField.class);
        String columnName = null;
        //如果注解存在
        if(joinField != null){
            //存在别名
            if(joinField.columnName().length() > 0){
                columnName = joinField.columnName();
            }
        }
        //否则转换名字
        if(columnName == null){
            columnName = StringUtil.javaToColumn(f.getName());
        }
        return columnName;
    }

    public String lambdaMethodNameToColumnName(LambdaPropertyFunction<?> name){
        String  fieldName =  LambdaUtils.lambdaMethodNameToFieldName(name);
        //尝试别名
        String columnName =  aliasMap.get(fieldName);
        if(columnName != null){
            return  columnName;
        }else{
            //使用字段构造别名
           Class clazz =   LambdaUtils.lambdaMethodNameToClassName(name);
           Field f =  ReflectionUtil.findField(clazz,fieldName);
           return  fieldToColumnName(f);
        }
    }

    @Override
    public void alias(String key, String value) {
        aliasMap.put(key,value);
    }

    @Override
    public void alias(Class clazz) {
        List<Field> fs =  ReflectionUtil.getAllDeclaredFields(clazz);
        for (Field f : fs) {
            String columnName =  fieldToColumnName(f);
            alias(f.getName(),columnName);
        }
    }

    @Override
    public String fieldToColumnName(String f) {
        String columnName =  aliasMap.get(f);
        if(columnName != null){
            return  columnName;
        }
        return StringUtil.javaToColumn(f);
    }
}
